package net.homeip.jcperera.nu.core.persistence;

import java.io.Serializable;

import javax.persistence.EntityManager;

import net.homeip.jcperera.nu.core.CoreBase;
import net.homeip.jcperera.nu.core.boot.Boot;
import net.homeip.jcperera.nu.core.config.Configuration;

import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.jpa.JpaEntityManager;

/**
 * <p>
 * EclipseLinkInfoAdapter is a function library class, whose only purpose is to provide functionality to the framework
 * about the underlying {@code EclipseLink} persistence provider. Functions in this library are higher level than some
 * other function libraries in the framework and therefore this conforms to the {@link CoreBase} interface in order to
 * use a {@link Log} inside any function when needed.
 * </p>
 * 
 * @name EclipseLinkInfoAdapter functions
 * @author julio.c.perera@gmail.com
 * @application nu
 * @since 0.1.0.0
 */
public class EclipseLinkInfoAdapter extends CoreBase implements Serializable
{
    // Required to implement Serializable interface
    private static final long  serialVersionUID = -8167519272476402357L;

    // CoreBase properties, for easy use from other components, as well as logging
    public static final int    runtimeLevel     = 0;
    public static final String moduleName       = "core";
    public static final String componentName    = "nu_core_persistence_eclipselink_adapter";

    public static final String targetDBpropName = "nu.db.target";

    /**
     * <p>
     * Using the underlying implementation of the {@code EclipseLink} persistence adapter, detects and return the target
     * database type (vendor in most of the cases), meaning one of the following values:
     * <ul>
     * <li>ORACLE</li>
     * <li>SQLSERVER</li>
     * <li>DB2</li>
     * <li>MYSQL</li>
     * <li>POSTGRESQL</li>
     * <li>ODBC</li>
     * <li>ACCESS</li>
     * <li>CLOUDSCAPE</li>
     * <li>DERBY</li>
     * <li><b>OTHER</b> - None of the above</li>
     * </ul>
     * </p>
     * <p>
     * Please notice that even when this function is capable of detecting the above listed database types this doesn't
     * mean that all of them will be supported by the framework.
     * </p>
     * <p>
     * The result of this query will be available in the system property named "nu.db.target", notice that this property
     * is not user modifiable.
     * </p>
     * 
     * @return the Target Database type Name (brand)
     */
    public static String determineTargetDatabase()
    {
        Configuration configuration = Boot.getSystem().getConfiguration();
        Persistence persistence = Boot.getSystem().getPersistence();

        String target = configuration.get(targetDBpropName);
        if (target == null || target.isEmpty())
        {
            EntityManager em = persistence.getEntityManagerFactory().createEntityManager();
            Platform platform = em.unwrap(JpaEntityManager.class).getServerSession().getDatasourcePlatform();
            if (platform.isOracle()) target = "ORACLE";
            else if (platform.isSQLServer()) target = "SQLSERVER";
            else if (platform.isDB2()) target = "DB2";
            else if (platform.isMySQL()) target = "MYSQL";
            else if (platform.isSybase()) target = "SYBASE";
            else if (platform.isPostgreSQL()) target = "POSTGRESQL";
            else if (platform.isODBC()) target = "ODBC";
            else if (platform.isAccess()) target = "ACCESS";
            else if (platform.isCloudscape()) target = "CLOUDSCAPE";
            else if (platform.isDerby()) target = "DERBY";
            else target = "OTHER";
            configuration.put(targetDBpropName, target);
        }
        return target;
    }
}